package javabean;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;

import java.io.File;
import java.util.*;

public class GenCode {

    static String prefix = "    ";
    static String fileName = "MerchantInfo";
    static File excelFile = FileUtil.newFile("D:/code/" + fileName + ".xlsx");
    static File fileTxt = FileUtil.newFile("D:/code/" + fileName + ".txt");

    public static void main(String[] args) {
        code();
        table();
    }

    private static void table() {
        List<String> content = new ArrayList<>();
        ExcelReader reader = ExcelUtil.getReader(excelFile);
        for (String sheetName : reader.getSheetNames()) {
            String[] split = sheetName.split("-");
            String tableName = split[0];
            String fileNameInner = StrUtil.upperFirst(StrUtil.toCamelCase(split[0]));

            StringBuilder sb = new StringBuilder();
            sb.append("\r\n");
            sb.append("CREATE TABLE " + tableName + " (").append("\r\n");
            sb.append(prefix).append("id bigint NOT NULL AUTO_INCREMENT,").append("\r\n");

            Set<String> propSet = new HashSet<>();

            File file = FileUtil.newFile("D:/code/" + fileName + "-table/" + fileNameInner + ".sql");

            List<Map<String, Object>> maps = ExcelUtil.getReader(excelFile, sheetName).readAll();
            for (Map<String, Object> map : maps) {
                String name = map.get("中文名").toString();
                String prop = map.get("参数").toString();
                if (propSet.contains(prop)) {
                    continue;
                }
                propSet.add(prop);
                if (prop.contains("<")) {
                    prop = prop.substring(0, prop.indexOf("<"));
                }

                sb.append(prefix).append(prop + " varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT '' COMMENT '" + name + "',").append("\r\n");
            }

            sb.append(prefix).append("PRIMARY KEY (`id`) USING BTREE").append("\r\n");
            sb.append(") ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='" + split[1] + "';").append("\r\n");

            FileUtil.writeUtf8String(sb.toString(), file);
        }
    }
    private static void code() {
        List<String> content = new ArrayList<>();
        ExcelReader reader = ExcelUtil.getReader(excelFile);
        for (String sheetName : reader.getSheetNames()) {

            String[] split = sheetName.split("-");
            String className = StrUtil.upperFirst(StrUtil.toCamelCase(split[0]));

            List<Map<String, Object>> maps = ExcelUtil.getReader(excelFile, sheetName).readAll();

            File file = FileUtil.newFile("D:/code/" + fileName + "-java/" + className + ".java");

            StringBuilder sb = new StringBuilder();

            sb.append("\r\n");

            sb.append("import cn.hutool.core.annotation.Alias;").append("\r\n");
            sb.append("import io.swagger.annotations.ApiModel;").append("\r\n");
            sb.append("import io.swagger.annotations.ApiModelProperty;").append("\r\n");
            sb.append("import lombok.Data;").append("\r\n");
            sb.append("import org.hibernate.validator.constraints.Length;").append("\r\n");
            sb.append("\r\n");

            sb.append("import javax.validation.Valid;").append("\r\n");
            sb.append("import javax.validation.constraints.NotBlank;").append("\r\n");
            sb.append("import javax.validation.constraints.NotEmpty;").append("\r\n");
            sb.append("import javax.validation.constraints.NotNull;").append("\r\n");
            sb.append("import javax.validation.constraints.Size;").append("\r\n");
            sb.append("import java.util.List;").append("\r\n");
            sb.append("\r\n");

            sb.append("@Data").append("\r\n");
            sb.append("@ApiModel(description = \"" + split[1] + "\")").append("\r\n");
            sb.append("public class " + className + " {").append("\r\n");
            sb.append("\r\n");

            Set<String> propSet = new HashSet<>();
            Set<String> propNeed = new LinkedHashSet<>();
            Set<String> propNameNeed = new LinkedHashSet<>();

            for (Map<String, Object> map : maps) {
                String name = map.get("中文名").toString();
                String desc = map.get("说明").toString();
                Integer size = 0;
                if (map.containsKey("长度")) {
                    Object len = map.get("长度");
                    if (len != null && NumberUtil.isNumber(len.toString())) {
                        size = Integer.parseInt(len.toString());
                    }
                }
                boolean need = BooleanUtil.toBoolean(map.get("必填").toString());

                String type;
                if (map.containsKey("类型")) {
                    type = map.get("类型").toString();
                } else {
                    type = map.get("定义").toString();
                }

                String prop = map.get("参数").toString();
                if (propSet.contains(prop)) {
                    continue;
                }
                propSet.add(prop);

                if (prop.contains("<")) {
                    prop = prop.substring(0, prop.indexOf("<"));
                }

                if (prop.startsWith("*")) {
                    prop = prop.replace("*", "");
                } else {
                    if (need) {
                        propNeed.add(prop);
                        propNameNeed.add(name + " [" + prop + "]");
                    }
                }
                String propName = StrUtil.toCamelCase(prop);

                String alias = StrUtil.format("@Alias(\"{}\")", prop);
                sb.append(prefix).append(alias).append("\r\n");

                String swagger = StrUtil.format("@ApiModelProperty(value = \"{}【{}】\", required = {})", name, desc.replaceAll("\n", ";"), need);
                sb.append(prefix).append(swagger).append("\r\n");

                if (name.contains("yyyyMMdd")) {
//                    "^(\\d{2,4})([/\\-.年]?)(\\d{1,2})([/\\-.月]?)(\\d{1,2})日?$"
                }

                if (type.equals("String")) {
                    if (need) {
                        String valid = StrUtil.format("@NotBlank(message = \"{}不能为空\")", propName);
                        sb.append(prefix).append(valid).append("\r\n");
                    }
                    String msg = propName + " 长度范围：1~" + size;
                    String valid = StrUtil.format("@Length(min = {}, max = {}, message = \"{}\")", 1, size, msg);
                    sb.append(prefix).append(valid).append("\r\n");
                    sb.append(prefix).append("private String " + propName + ";").append("\r\n");
                }
                if (type.equals("List")) {
                    sb.append(prefix).append("@Valid").append("\r\n");
                    if (need) {
                        String msg = propName + " 不能为空";
                        String valid = StrUtil.format("@Size(min={}, message = \"{}\")", 1, msg);
                        sb.append(prefix).append(valid).append("\r\n");
                    }
                    String clzName = StrUtil.upperFirst(StrUtil.toCamelCase(propName));
                    sb.append(prefix).append("private List<" + clzName + "> " + propName + ";").append("\r\n");
                }
                if (type.equals("Object")) {
                    sb.append(prefix).append("@Valid").append("\r\n");

                    String valid = StrUtil.format("@NotNull(message = \"{} 不能为空\")", 1, propName);
                    sb.append(prefix).append(valid).append("\r\n");

                    String clzName = StrUtil.upperFirst(StrUtil.toCamelCase(propName));
                    sb.append(prefix).append("private " + clzName + " " + propName + ";").append("\r\n");
                }

                sb.append("\r\n");
            }

            sb.append("}");
            FileUtil.writeUtf8String(sb.toString(), file);

            content.add(className + " 必填数据（" + propNeed.size() + "）：" + "\r\n");
            content.add(StrUtil.join(", ", propNeed) + "\r\n");
            content.add(StrUtil.join("\r\n", propNameNeed) + "\r\n");
            content.add("---------------------------------------------");
        }

        FileUtil.writeUtf8Lines(content, fileTxt);
    }
}
